package javaagent.jvmtool;


import javassist.*;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.*;
import java.util.stream.Collectors;


public class ToolServiceImpl extends UnicastRemoteObject implements ToolService {
    public ToolServiceImpl() throws RemoteException {
    }


    @Override
    public String findClassName(String name) throws RemoteException {
        return Arrays.stream(Agent.instrumentation.getAllLoadedClasses())
                .filter(s -> s.getName().toUpperCase().contains(name.toUpperCase()))
                .limit(20)
                .map(Class::getName)
                .collect(Collectors.joining("\r\n"));
    }

    @Override
    public String jadClass(String className) throws RemoteException {
        try {
            return Jad.decompiler(className);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @Override
    public String findMethod(String className) throws RemoteException {
        String className1 = findClassName(className);
        ClassPool pool = new ClassPool();
        pool.appendSystemPath();
        try {
            CtClass ctClass = pool.get(className1);
            CtMethod[] declaredMethods = ctClass.getDeclaredMethods();
            List<String> strings = new ArrayList<>(declaredMethods.length);
            for (CtMethod declaredMethod : declaredMethods) {
                strings.add(declaredMethod.getName());
            }
            return strings.toString();
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String testMethod(String name) throws RemoteException {
        // todo 研究下javassist设置返回值 通过反射获取返回控制台
        Class[] allLoadedClasses = Agent.instrumentation.getAllLoadedClasses();
        String[] names = new String[allLoadedClasses.length];
        for (int i = 0; i < allLoadedClasses.length; i++) {
            names[i] = allLoadedClasses[i].getName();
        }
        ClassPool pool = new ClassPool();
        pool.appendSystemPath();
        try {
            CtClass ctClasses = pool.get("javaagent.HelloWorld");
            CtMethod method = ctClasses.getDeclaredMethod(name);
            method.addLocalVariable("l", CtClass.longType);
            method.insertBefore("l = System.currentTimeMillis();");
            method.insertAfter("System.out.println(\"执行时间：\" + System.currentTimeMillis());");
            ctClasses.toClass();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "成功";
    }
}
